from abc import ABC, abstractmethod

# Device Parts
class DevicePart(ABC):
    @abstractmethod
    def accept(self, visitor):
        pass

class Computer(DevicePart):
    def __init__(self, chassis, monitor):
        self.chassis = chassis
        self.monitor = monitor

    def accept(self, visitor):
        visitor.visit_computer(self)
        self.chassis.accept(visitor)
        self.monitor.accept(visitor)

class Chassis(DevicePart):
    def __init__(self, harddisk, switch):
        self.harddisk = harddisk
        self.switch = switch

    def accept(self, visitor):
        visitor.visit_chassis(self)
        self.harddisk.accept(visitor)
        self.switch.accept(visitor)

class Harddisk(DevicePart):
    def accept(self, visitor):
        visitor.visit_harddisk(self)

class Monitor(DevicePart):
    def __init__(self, switch):
        self.switch = switch

    def accept(self, visitor):
        visitor.visit_monitor(self)
        self.switch.accept(visitor)

class Switch(DevicePart):
    def __init__(self, name):
        self.name = name

    def close(self):
        print(f"{self.name} switch closed")

    def accept(self, visitor):
        visitor.visit_switch(self)

# Visitor Interface
class DeviceVisitor:
    def visit_computer(self, computer):
        pass

    def visit_chassis(self, chassis):
        pass

    def visit_harddisk(self, harddisk):
        pass

    def visit_monitor(self, monitor):
        pass

    def visit_switch(self, switch):
        pass

if __name__ == "__main__":
    computer = Computer(
        Chassis(Harddisk(), Switch("chassis")),
        Monitor(Switch("monitor"))
    )

    # Visitor implementation
    class SwitchCloserVisitor(DeviceVisitor):
        def visit_switch(self, switch):
            switch.close()

    visitor = SwitchCloserVisitor()
    computer.accept(visitor)
